<template>
  <div>
    <quill-editor v-model="content" ref="myQuillEditor" style="width:100%;" :options="editorOption" >
    </quill-editor>
    <a-modal
      title="请选择图片"
      centered
      v-model="modal1Visible"
      :footer="null"
      :width="400"
      :maskClosable="true"
    >
      <a-upload v-if="modal1Visible" name="file" :multiple="true" action="" :customRequest="beforeUpload" accept="image/gif,image/jpeg,image/jpg,image/png,image/svg" >
        <a-button style="margin:0 auto">
          <a-icon type="upload" /> 选择图片
        </a-button>
      </a-upload>
    </a-modal>
  </div>
</template>
<script>
import { quillEditor } from "vue-quill-editor";
import * as Quill from "quill";
import imageResize from "quill-image-resize-module";
import "quill/dist/quill.core.css";
import "quill/dist/quill.snow.css";
import "quill/dist/quill.bubble.css";
//quill编辑器的字体
var fonts = [
  "sans-serif",
  "SimSun",
  "SimHei",
  "Microsoft-YaHei",
  "KaiTi",
  "FangSong",
  "Arial",
  "Times-New-Roman"
];
var Font = Quill.import("formats/font");
Font.whitelist = fonts; //将字体加入到白名单
Quill.register(Font, true);
Quill.register("modules/imageResize", imageResize);
export default{
  name: "QuillEditor",
  components: { quillEditor },
  props:{
      richText:{
          type:String,
          default:''
      }
  },
  data() {
    return {
      content: "", //富文本绑定的值
      //富文本编辑器配置
      editorOption: {
        modules: {
          imageResize: {},
          toolbar: [
            "bold",
            "italic",
            "underline",
            "strike",
            "blockquote",
            "code-block",
            "image",
            "video",
            "clean",
            { color: [] },
            { background: [] },
            { align: [] },
            { font: fonts },
            { size: ["small", false, "large", "huge"] },
            { header: [1, 2, 3, 4, 5, 6, false] }
          ],
        },
        theme:'snow'
      }, //富文本编辑器配置
      modal1Visible:false,
      existArr:[],//数据库存在url
      saveUrl:[],//当前需要把状态置为保存状态的图片
    };
  },
  mounted(){
      this.content = this.$props.richText;
      this.existArr = this.getRichSrc(this.$props.richText);
      this.$nextTick(()=>{
        let toolbar = this.$refs.myQuillEditor.quill.getModule('toolbar');
        toolbar.addHandler('image', () => {
          this.modal1Visible = true;
        });
      })
  },
  methods: {
    //失去焦点方法
    // quillBlur(e) {
    //   // this.getBase64();
    //   this.$emit('quillBlur',this.content);
    // },
    //富文本中获取base64字符串
    getBase64(){
      const _html = this.content;
      var imgArr = _html.match(/<img[^>]*>/gim) || [];
      var regExp = /src="data:image\/[^"]*(?=")|src='data:image\/[^']*(?=')/gim;
      var matchArr = [];
      for (var i = 0; i < imgArr.length; i++) {
        if(imgArr[i].match(regExp) && imgArr[i].match(regExp)[0]){
          matchArr.push(imgArr[i].match(regExp)[0].substring(5,imgArr[i].match(regExp)[0].length));
        }
      }
      return matchArr;
    },
    //点击选择图片
    beforeUpload(e){
      var file = e.file;
      if (!/image\/\w+/.test(file.type)) {
          return;
      }
      this.compressImage(file,1).then(res => {
        const quill = this.$refs.myQuillEditor.quill;
        const range = quill.getSelection();
        if (range) {
          quill.insertEmbed(range.index, 'image', res);
          quill.setSelection((range.index+1),range.length);
          this.modal1Visible = false;
        }
      })
      return false;
    },
    /**
     * 压缩图片(默认300k开始压缩)返回压缩后的图片和图片的base64
     * files压缩的图片
     * cb 压缩完成后回调函数
     * beginCompress图片超过多少开始压缩（单位m，默认0.3）
     */
    compressImage(file,beginCompress){
      return new Promise((resolve,reject) => {
        var canvas = document.createElement('canvas');
        var reader = new FileReader();
        reader.readAsDataURL(file);
        reader.onloadend = function (e) {
            if (!canvas || !canvas.getContext||(isNaN(beginCompress)?0.3:beginCompress) * 1024 * 1024 >= file.size) {
                resolve(e.target.result);
            } else {
                var image = new Image();
                image.src = e.target.result;
                image.onload = function () {
                    var context = canvas.getContext('2d');
                    canvas.width = image.width;
                    canvas.height = image.height;
                    context.drawImage(image, 0, 0, image.width, image.height);
                    var data = canvas.toDataURL(file.type, 0.8);
                    resolve(data);
                }
            }                            
        }
      })
    },
    //富文本中获取src(除了base64)
    getRichSrc(text) {
      var imgArr = text.match(/<img[^>]*>/gim) || [];
      var srcArr = [];
      var urlArr = [];//(?<=").*?(?=");  /(?<=src=")[^"]+(?=")|(?<=src=')[^']+(?=')/gi
      var regExp = /src="[^"]+(?=")|src='[^'][^']+(?=')/gi;
      for (var i = 0; i < imgArr.length; i++) {
        srcArr = srcArr.concat(imgArr[i].match(regExp) || []);
      }
      for (var i = 0; i < srcArr.length; i++) {
        if(srcArr[i].match(/src="data:image|src='data:image/g)){
          continue;
        }
        urlArr.push(srcArr[i].substring(5, srcArr[i].length));
      }
      return urlArr;
    },
    //将base64转换为文件
    dataURLtoFile2(dataurl, filename) {
      var arr = dataurl.split(','), mime = arr[0].match(/:(.*?);/)[1],
      bstr = window.atob ? atob(arr[1]) : this.atob(arr[1]), n = bstr.length, u8arr = new Uint8Array(n);
      while (n--) {
          u8arr[n] = bstr.charCodeAt(n);
      }
      try{
          return new File([u8arr], filename || "123." + mime.split("/")[1], { type: mime });
      } catch(ex) {
          var blob = new Blob([u8arr], { type: mime });
          blob.lastModifiedDate = new Date();
          blob.lastModified = Date.now()
          blob.name = filename || "123." + mime.split("/")[1];
          return blob;
      }
    },
    //base64解密(兼容ie9)
    atob:function(s){//解密
        s = s.replace(/\s|=/g, '');
        var cur,
            prev,
            mod,
            i = 0,
            result = [],
            base64hash = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/';
        while (i < s.length) {
            cur = base64hash.indexOf(s.charAt(i));
            mod = i % 4;

            switch (mod) {
                case 0:
                    //TODO
                    break;
                case 1:
                    result.push(String.fromCharCode(prev << 2 | cur >> 4));
                    break;
                case 2:
                    result.push(String.fromCharCode((prev & 0x0f) << 4 | cur >> 2));
                    break;
                case 3:
                    result.push(String.fromCharCode((prev & 3) << 6 | cur));
                    break;
                        
            }

            prev = cur;
            i ++;
        }

        return result.join('');
    },
    //对比两个数组找出第一个数组比第二个数组多的项，返回数组
    richArrCampare(arr1,arr2){
      var returnArr = arr1.concat();
      var j = returnArr.length;
      for(var i=0;i<arr2.length;i++){
          var j = returnArr.length;
          while(j--){
              if(returnArr[j]==arr2[i]){
                  returnArr.splice(j,1);
              }
          }
      }
      return returnArr;
    },
    //提交图片
    commitImage(){
      const _this = this;
      return new Promise((resolve,reject) => {
        let matchArr = this.getBase64();
        if(matchArr.length > 0){
          var formData = new FormData();
          for (var i = 0; i < matchArr.length; i++) {
              var fileData = _this.dataURLtoFile2(matchArr[i]);
              formData.append(i, fileData, fileData.name);
          }
          _this.request({
            url:"/common/upload",
            contentType:'multipart/form-data;charset=UTF-8',
            data: formData,
            success:(res)=>{
              var imgIndex = 0;
              let _html = _this.content;
              let uploaTxt = _html.replace(/<img(\S|\s)(src="data:image\/[^"]*"|src='data:image\/[^']*')[^>]*>/gim, function (match, pos, originalText) {
                  match = match.replace(/src=("(\S*)"|'(\S*)')/gim, 'src="'+res[imgIndex]+'"');
                  imgIndex++;
                  return match;
              })
              _this.content = uploaTxt;
              let arr = [];
              for(var key in res){
                arr.push(res[key]);
              }
              _this.saveUrl = arr;
              resolve({richText:uploaTxt,saveCb:_this.saveCb});
            },
            error:(res) => {
              reject(res);
            }
          })
        }else{
          resolve({richText:_this.content,saveCb:_this.saveCb})
        }
        
      })
    },
    //提交数据后回调
    saveCb(){
      const _this = this;
      return new Promise((resolve,reject) => {
        let commitUrl = _this.getRichSrc(_this.content);
        let delUrl = _this.richArrCampare(_this.existArr,commitUrl);
        if(delUrl.length==0&&_this.saveUrl.length==0){
          resolve();
        }else{
          //改变OSS状态
          this.request({
            url:"/common/changeFileTags",
            type:"post",
            data: {
              newFile:_this.saveUrl, 
              deleteFile:delUrl
            },
            success:(res)=>{
              resolve(res);
            },
            error:(res)=>{
              reject(res);
            }
          })
        }        
      })
    }
  },
  watch:{
    richText(val){
      this.content = val;
    }
  }
}
</script>

